package dongze.com.ckdj.adapter;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.databinding.Observable;
import android.databinding.ViewDataBinding;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.ResultReceiver;
import android.support.annotation.CallSuper;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;

import com.android.databinding.library.baseAdapters.BR;

import org.greenrobot.greendao.query.QueryBuilder;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import dongze.com.ckdj.R;
import dongze.com.ckdj.activity.ImageCaptureActivity;
import dongze.com.ckdj.data.IRecordRequestBuilder;
import dongze.com.ckdj.data.entity.request.RecordOption;
import dongze.com.ckdj.data.entity.request.RecordRequestBody;
import dongze.com.ckdj.databinding.InformationItemEditTextBinding;
import dongze.com.ckdj.databinding.InformationItemPhotoBinding;
import dongze.com.ckdj.databinding.InformationItemRadioBinding;
import dongze.com.ckdj.databinding.InformationItemSpinnerBinding;
import dongze.com.ckdj.databinding.InformationItemTextBinding;
import dongze.com.ckdj.databinding.model.InformationItemPhotoModel;
import dongze.com.ckdj.databinding.model.InformationItemRadioModel;
import dongze.com.ckdj.databinding.model.InformationItemSpinnerModel;
import dongze.com.ckdj.databinding.model.InformationItemTextModel;
import dongze.com.ckdj.persistence.DaoHelper;
import dongze.com.ckdj.persistence.dao.DaoSession;
import dongze.com.ckdj.persistence.dao.Image;
import dongze.com.ckdj.persistence.dao.ImageDao;
import dongze.com.ckdj.persistence.dao.ServerUploadTask;
import dongze.com.ckdj.persistence.dao.ServerUploadTaskDao;
import dongze.com.ckdj.service.ImageUploadTask;
import dongze.com.ckdj.ui.ImageUploadDialog;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;

/**
 * Created by fanqwz on 2017/7/21.
 */

public class CheckInOperationAdapter extends BaseAdapter implements IRecordRequestBuilder {
    List<TypedListItem> listItems;
    Map<TypedListItem, Object> values;
    View.OnClickListener massLossBtnListener;
    boolean isHightlight = false;

    Context context;
    DaoSession daoSession;
    Handler handler;

    public CheckInOperationAdapter(Context context, DaoSession daoSession, List<TypedListItem> listItems, View.OnClickListener massLossBtn) {
        this.listItems = listItems;
        this.context = context;
        this.daoSession = daoSession;
        values = new HashMap<>(listItems.size());
        massLossBtnListener = massLossBtn;
        handler = new Handler(Looper.getMainLooper());
    }

    @Override
    public int getCount() {
        return listItems == null ? 0 : listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return listItems == null ? null : listItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public int getItemViewType(int position) {
        return listItems.get(position).getType().ordinal();
    }

    @Override
    public int getViewTypeCount() {
        return TypedListItem.Type.values().length;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        switch (listItems.get(position).getType()) {
            case TEXT:
                convertView = getTextItemView(position, convertView, parent);
                break;
            case EDITTEXT:
                convertView = getEditTextItemView(position, convertView, parent);
                break;
            case SPINNER:
                convertView = getSpinnerItemView(position, convertView, parent);
                break;
            case RADIO:
                convertView = getRadioItemView(position, convertView, parent);
                break;
            case PHOTO:
                convertView = getPhotoItemView(position, convertView, parent);
                break;
        }

        Holder holder = (Holder) convertView.getTag();
        holder.bind(listItems.get(position));
        return convertView;
    }

    private View putMassLossBtnInLayout(ViewGroup parent, View convertview) {
        final ViewGroup root = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_with_mass_loss_btn, parent, false);
        root.findViewById(R.id.mass_loss_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (massLossBtnListener != null)
                    massLossBtnListener.onClick(v);
            }
        });
        ((ViewGroup) root.findViewById(R.id.container)).addView(convertview);
        return root;
    }

    private View getTextItemView(int position, View convertView, ViewGroup parent) {
        if (convertView == null || ((Holder) convertView.getTag()).type != listItems.get(position).type) {
            InformationItemTextBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.information_item_text, null, false);
            convertView = binding.getRoot();
            TextHolder holder = new TextHolder();
            holder.type = listItems.get(position).type;
            holder.bindingComponent = binding;
            binding.setVehicleInformationItemText(holder.model);
            convertView = putMassLossBtnInLayout(parent, convertView);
            convertView.setTag(holder);
        }

        return convertView;
    }

    private View getEditTextItemView(int position, View convertView, ViewGroup parent) {
        if (convertView == null || ((Holder) convertView.getTag()).type != listItems.get(position).type) {
            InformationItemEditTextBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.information_item_edit_text, null, false);
            convertView = binding.getRoot();
            EditTextHolder holder = new EditTextHolder();
            holder.type = listItems.get(position).type;
            holder.bindingComponent = binding;
            binding.setVehicleInformationItemText(holder.model);
            convertView = putMassLossBtnInLayout(parent, convertView);
            convertView.setTag(holder);
        }

        return convertView;
    }

    private View getSpinnerItemView(int position, View convertView, ViewGroup parent) {
        if (convertView == null || ((Holder) convertView.getTag()).type != listItems.get(position).type) {
            InformationItemSpinnerBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.information_item_spinner, null, false);
            convertView = binding.getRoot();
            SpinnerHolder holder = new SpinnerHolder();
            holder.type = listItems.get(position).type;
            holder.bindingComponent = binding;
            binding.setVehicleInformationItemSpinner(holder.model);
            convertView = putMassLossBtnInLayout(parent, convertView);
            convertView.setTag(holder);
        }

        return convertView;
    }

    private View getRadioItemView(int position, View convertView, ViewGroup parent) {
        if (convertView == null || ((Holder) convertView.getTag()).type != listItems.get(position).type) {
            InformationItemRadioBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.information_item_radio, null, false);
            convertView = binding.getRoot();
            RadioHolder holder = new RadioHolder();
            holder.type = listItems.get(position).type;
            holder.bindingComponent = binding;
            binding.setVehicleInformationItemRadio(holder.model);
            convertView = putMassLossBtnInLayout(parent, convertView);
            convertView.setTag(holder);
        }

        if (isHightlight && values.get(listItems.get(position)) != null) {
            convertView.setBackgroundColor(convertView.getResources().getColor(android.R.color.darker_gray));
        } else {
            convertView.setBackgroundColor(0xFFFFFFFF);
        }

        return convertView;
    }

    private View getPhotoItemView(int position, View convertView, ViewGroup parent) {
        if (convertView == null || ((Holder) convertView.getTag()).type != listItems.get(position).type) {
            InformationItemPhotoBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.information_item_photo, null, false);
            convertView = binding.getRoot();
            final PhotoHolder holder = new PhotoHolder(convertView);
            holder.type = listItems.get(position).type;
            holder.bindingComponent = binding;
            binding.setVehicleInformationItemPhoto(holder.model);
            convertView.setTag(holder);
        }

        convertView.setBackgroundColor(0xFFEEEEEE);
        return convertView;
    }

    @Override
    public io.reactivex.Observable<RecordRequestBody> build(final RecordRequestBody body) {
        return io.reactivex.Observable.create(new ObservableOnSubscribe<RecordRequestBody>() {
            @Override
            public void subscribe(final ObservableEmitter<RecordRequestBody> e) throws Exception {
                final List<ImageUploadTask> tasks = new ArrayList<>();
                final Map<Long, RecordOption> map = new HashMap<>();
                List<RecordOption> imgRcrd = new ArrayList<>();
                List<File> imgs = new ArrayList<>(20);

                for (TypedListItem item : listItems) {
                    RecordOption r = new RecordOption();
                    r.setProgram_id(item.getId());
                    r.setProgram_name(item.getKey());
                    r.setProgram_type(item.getType().toData());
                    r.setProgram_sort(item.getSort());
                    body.getOptions().add(r);

                    if (item.type == TypedListItem.Type.PHOTO) {
                        List<String> imgsStr = null;
                        imgRcrd.add(r);

                        imgsStr = (List<String>) values.get(item);
                        if (imgsStr == null || imgsStr.size() == 0) {
                            new AlertDialog.Builder(context)
                                    .setMessage(item.getKey() + "没有拍照")
                                    .create()
                                    .show();
                            e.onError(new Exception(item.getKey() + "没有拍照"));
                            return;
                        }

                        for (String s : imgsStr) {
                            if (!TextUtils.isEmpty(s)) {
                                File f = new File(s);
                                if (f.exists())
                                    imgs.add(f);
                                ImageUploadTask task = DaoHelper.createImageTask(daoSession, s);
                                tasks.add(task);
                                map.put(task.getId(), r);
                            }
                        }

//                        item.setValue((String) values.get(item));
                    } else {
                        Object v = values.get(item);
                        r.setProgram_value(v == null ? null : (String) v);
                        item.setValue((String) values.get(item));
                    }

                    if (TextUtils.isEmpty(r.getProgram_value())) {
                        isHightlight = true;
                        CheckInOperationAdapter.this.notifyDataSetChanged();
                    }

                }

                //check no null
                for (RecordOption option : body.getOptions()) {
                    if (option.getProgram_type() == TypedListItem.Type.RADIO.toData()
                            && TextUtils.isEmpty(option.getProgram_value())) {
                        new AlertDialog.Builder(context)
                                .setMessage("点检项目：" + option.getProgram_name() + "没有填写")
                                .create()
                                .show();
                        e.onError(new Exception("点检项目：" + option.getProgram_name() + "没有填写"));
                        return;
                    }
                }


                if (imgs.size() > 0) {
                    // upload image
                    ImageUploadDialog dialog = new ImageUploadDialog(context, tasks, imgs, new ImageUploadDialog.CallBack() {
                        @Override
                        public void onTaskFinished(ImageUploadTask task) {

                        }

                        @Override
                        public void onAllTaskFinished() {
                            daoSession.clear();
                            for (ImageUploadTask task : tasks) {
                                QueryBuilder<Image> qb = daoSession.getImageDao().queryBuilder();
                                qb.join(ImageDao.Properties.Id, ServerUploadTask.class, ServerUploadTaskDao.Properties.ImageId)
                                        .where(ServerUploadTaskDao.Properties.Id.eq(task.getId()));
                                Image image = qb.unique();
                                RecordOption rcd = map.get(task.getId());

                                if (!TextUtils.isEmpty(rcd.getProgram_value()))
                                    rcd.setProgram_value(rcd.getProgram_value().concat(";") + image.getServerPath());
                                else
                                    rcd.setProgram_value(image.getServerPath());
                            }
                            e.onNext(body);
                            e.onComplete();
                        }
                    });
                    dialog.show();
                } else {
                    e.onNext(body);
                    e.onComplete();
                }
            }
        });
    }

    class Holder<T extends ViewDataBinding> {
        TypedListItem item;
        TypedListItem.Type type;
        T bindingComponent;

        @CallSuper
        public void bind(TypedListItem item) {
            this.item = item;
        }
    }

    // values的databinding值保存逻辑有些混乱，尽量不要改，省得麻烦
    class RadioHolder extends Holder<InformationItemRadioBinding> {
        InformationItemRadioModel model = new InformationItemRadioModel();

        RadioHolder() {
            model.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
                @Override
                public void onPropertyChanged(Observable sender, int propertyId) {
                    if (item.options == null || BR.position != propertyId)
                        return;

                    for (TypedListItem.Option o :
                            item.options) {
                        if (TextUtils.equals(o.getDislayname(), model.getPosition())) {
                            values.put(item, o.getValue());
                            break;
                        }
                    }
                }
            });
        }

        @Override
        public void bind(TypedListItem item) {
            super.bind(item);
            model.setKey(item.getKey());
            String[] arr = new String[item.getOptions().size()];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = item.getOptions().get(i).getDislayname();
            }
            model.setValues(arr);

            // model.setValues(arr) 会清空view，所以要重新设置position，先设null，防止setter过滤
            model.setPosition(null);
            if (values.get(item) != null) {
                model.setPosition((String) values.get(item));
            } else if (item.value != null) {
                model.setPosition(item.value);
            } else {
//                model.setPosition(arr.length > 0 ? arr[0] : "");
            }

//            bindingComponent.setVehicleInformationItemRadio(model);
        }
    }

    class SpinnerHolder extends Holder<InformationItemSpinnerBinding> {
        InformationItemSpinnerModel model = new InformationItemSpinnerModel();

        SpinnerHolder() {
            model.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
                @Override
                public void onPropertyChanged(Observable sender, int propertyId) {
                    if (item.options == null || BR.position != propertyId)
                        return;

                    if (model.getValues() != null && model.getValues().length > 0 && model.getPosition() > 0 && model.getPosition() < model.getValues().length) {
                        for (TypedListItem.Option o :
                                item.options) {
                            if (TextUtils.equals(o.getDislayname(), model.getValues()[model.getPosition()])) {
                                values.put(item, o.getValue());
                                break;
                            }
                        }
                    } else {
                        values.put(item, null);
                    }
                }
            });
        }

        @Override
        public void bind(TypedListItem item) {
            super.bind(item);
            model.setKey(item.getKey());
            String[] arr = new String[item.getOptions().size()];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = item.getOptions().get(i).getDislayname();
            }
            model.setValues(arr);
            model.setPosition(0);

            for (int i = 0; i < arr.length; i++) {
                if (TextUtils.equals((CharSequence) values.get(item), item.getOptions().get(i).getValue())) {
                    model.setPosition(i);
                    break;
                }
            }

//            bindingComponent.setVehicleInformationItemSpinner(model);
        }
    }

    class TextHolder extends Holder<InformationItemTextBinding> {
        InformationItemTextModel model = new InformationItemTextModel();

        TextHolder() {
        }

        @Override
        public void bind(TypedListItem item) {
            super.bind(item);
            model.setKey(item.getKey());
            model.setValue(item.getValue());
//            bindingComponent.setVehicleInformationItemText(model);
        }
    }

    class EditTextHolder extends Holder<InformationItemEditTextBinding> {
        InformationItemTextModel model = new InformationItemTextModel();

        EditTextHolder() {
            model.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
                @Override
                public void onPropertyChanged(Observable sender, int propertyId) {
                    if (BR.value != propertyId)
                        return;

                    values.put(item, model.getValue());
                }
            });
        }

        @Override
        public void bind(TypedListItem item) {
            super.bind(item);
            model.setKey(item.getKey());
            model.setValue((String) values.get(item));
//            bindingComponent.setVehicleInformationItemText(model);
        }
    }

    class PhotoHolder extends Holder<InformationItemPhotoBinding> {
        ResultReceiver resultReceiver = new ResultReceiver(handler) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                super.onReceiveResult(resultCode, resultData);

                if (resultCode == Activity.RESULT_OK && resultData != null) {
                    List<String> imgs = resultData.getStringArrayList("imgs");

                    if (imgs == null)
                        return;

                    model.setImgs(imgs);
                }
            }
        };
        InformationItemPhotoModel model;
        View itemview;
        Button button;
        PhotoHolder(View itemview) {
            model = new InformationItemPhotoModel();
            model.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
                @Override
                public void onPropertyChanged(Observable sender, int propertyId) {
                    if (propertyId == dongze.com.ckdj.BR.imgs) {
                        values.put(item, model.getImgs());
                    }
                }
            });

            this.itemview = itemview;
            this.button = itemview.findViewById(R.id.capture);
        }

        @Override
        public void bind(final TypedListItem item) {
            super.bind(item);
            model.setKey(item.getKey());
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(context, ImageCaptureActivity.class);
                    intent.putExtra("result_receiver", resultReceiver);
                    intent.putStringArrayListExtra("imgs", (ArrayList<String>) values.get(item));
                    context.startActivity(intent);
                }
            });

            List<String> imgs = (List<String>) values.get(item);
            model.setImgs(imgs);
        }
    }
}
